package org.jeecg.modules.deepseek.controller.steam;


import cn.hutool.json.JSONUtil;
import dev.langchain4j.data.document.Metadata;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.store.embedding.EmbeddingMatch;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.config.deepseek.ChatRequestBean;
import org.jeecg.config.shiro.IgnoreAuth;
import org.jeecg.modules.deepseek.pojo.ChatRequest;

import org.jeecg.modules.deepseek.pojo.ChatRequestExample;
import org.jeecg.modules.deepseek.pojo.Note;
import org.jeecg.modules.deepseek.pojo.NoteData;
import org.jeecg.modules.deepseek.service.NoteService;
import org.jeecg.modules.deepseek.tools.WebNoteTools;
import org.springframework.ai.model.function.FunctionCallback;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@Slf4j
@RestController
@RequestMapping("/note/api")
public class NoteController {
    @Autowired
    private NoteService noteService;

    @Autowired
    ChatRequestBean chatRequestBean;

    // 保存笔记
    @PostMapping("/save")
    @IgnoreAuth

    public Result<String> saveNote(@RequestBody NoteData note) {

        ChatRequest.Message system = new ChatRequest.Message("system", "你是一个笔记助手,可以存储和检索用户输入的内容一定要调用函数");
        String jsonStr = JSONUtil.toJsonStr(note);
        ChatRequest.Message user = new ChatRequest.Message("user", "用户存储的内容:"+jsonStr);
        ResponseEntity<OpenAiApi.ChatCompletion>
                chatCompletionChunkResponseEntity1 = null;
        OpenAiApi.ChatCompletionRequest currentWeather = chatRequestBean.createChatRequestFunctionNote();
        Map<String, ToolCallback> functionCallbackRegister = chatRequestBean.ToosBeanFetcher();
        List<OpenAiApi.FunctionTool> tools = currentWeather.tools();
        List<ChatRequest.Message> messages = new ArrayList<>(List.of(system, user));
        ResponseEntity<OpenAiApi.ChatCompletion> chatCompletionChunkResponseEntity = ChatRequestExample.requestDeepSeekChat(tools, messages);
        OpenAiApi.ChatCompletion body = chatCompletionChunkResponseEntity.getBody();
        if (body == null) {
            return Result.error("失败");
        }
        List<OpenAiApi.ChatCompletion.Choice> choices = body.choices();
        if (choices.isEmpty()) {
            return Result.error("失败");
        }
        List<OpenAiApi.ChatCompletionMessage.ToolCall> toolCalls = body.choices().get(0).message().toolCalls();
        if (toolCalls == null || toolCalls.isEmpty()) {
            return Result.error("失败");
        }
        for (OpenAiApi.ChatCompletion.Choice choice : body.choices()) {
            List<OpenAiApi.ChatCompletionMessage.ToolCall> toolCalls1 = choice.message().toolCalls();
            //TODO 管理添加的功能，需要人工二次确认才可行
            Iterator<OpenAiApi.ChatCompletionMessage.ToolCall> iterator = toolCalls1.iterator();
            while (iterator.hasNext()) {
                OpenAiApi.ChatCompletionMessage.ToolCall toolCall = iterator.next(); // 获取当前元素
                FunctionCallback functionCallback = functionCallbackRegister.get(toolCall.function().name());
                String arguments = toolCall.function().arguments();
                String s = JSONUtil.formatJsonStr(arguments);
                String call = functionCallback.call(s);
                log.info("查看出入内容{}",call);
                // 如果不是最后一个元素，继续迭代
                if (iterator.hasNext()) {
                } else {
                }
            }
        }

        return Result.ok("内容添加成功");
    }


    // 获取所有笔记
    @PostMapping("/search/notes")
    @IgnoreAuth
    public ResponseEntity<List<Map<String, Object>>> getAllNotes(@RequestBody  WebNoteTools.NoteSearchRequest request) {
        log.info("请求参数：{}",request);

        List<EmbeddingMatch<TextSegment>> embeddingMatches = noteService.searchNotes(request);

        log.info("查看已经获取的笔记条数:{}",embeddingMatches.size());
        List<Map<String, Object>> resultList = new ArrayList<>();

        // 2. 遍历每一个 embeddingMatch 对象
        for (EmbeddingMatch<TextSegment> match : embeddingMatches) {
            // 从 match 中提取 text 和 metadata
            String text = match.embedded().text();
            Map<String, Object> metadataMap = match.embedded().metadata().toMap();

            // 3. 创建一个新的 Map 用于封装
            Map<String, Object> combinedMap = new HashMap<>();
            combinedMap.put("text", text);
            combinedMap.put("metadata", metadataMap); // 将 metadataMap 整体放入

            // 4. 将封装好的 Map 添加到结果列表中
            resultList.add(combinedMap);
        }

        return ResponseEntity.ok(resultList);
    }

    // 检索特定种类笔记
    @PostMapping("/search")
    @IgnoreAuth
    public ResponseEntity<String> searchNotes(@RequestBody Note category) {
        ChatRequest.Message system = new ChatRequest.Message("system", "你是一个笔记助手,请把用户的需要检索的内容从向量数据库中检索出来");
        String jsonStr = JSONUtil.toJsonStr(category);
        ChatRequest.Message user = new ChatRequest.Message("user", "用户检索的内容" + jsonStr);
        ResponseEntity<OpenAiApi.ChatCompletion>
                chatCompletionChunkResponseEntity1 = null;
        OpenAiApi.ChatCompletionRequest currentWeather = chatRequestBean.createChatRequestFunctionNote();
        Map<String, ToolCallback> functionCallbackRegister = chatRequestBean.ToosBeanFetcher();
        List<OpenAiApi.FunctionTool> tools = currentWeather.tools();
        List<ChatRequest.Message> messages = new ArrayList<>(List.of(system, user));
        ResponseEntity<OpenAiApi.ChatCompletion> chatCompletionChunkResponseEntity = ChatRequestExample.requestDeepSeekChat(tools, messages);
        OpenAiApi.ChatCompletion body = chatCompletionChunkResponseEntity.getBody();
        if (body == null) {

            return ResponseEntity.ofNullable("失败");
        }
        List<OpenAiApi.ChatCompletion.Choice> choices = body.choices();
        if (choices.isEmpty()) {
            return ResponseEntity.ofNullable("失败");
        }
        List<OpenAiApi.ChatCompletionMessage.ToolCall> toolCalls = body.choices().get(0).message().toolCalls();
        if (toolCalls == null || toolCalls.isEmpty()) {
            return ResponseEntity.ofNullable("失败");
        }
        for (OpenAiApi.ChatCompletion.Choice choice : body.choices()) {
            List<OpenAiApi.ChatCompletionMessage.ToolCall> toolCalls1 = choice.message().toolCalls();
            //TODO 管理添加的功能，需要人工二次确认才可行
            Iterator<OpenAiApi.ChatCompletionMessage.ToolCall> iterator = toolCalls1.iterator();
            while (iterator.hasNext()) {
                OpenAiApi.ChatCompletionMessage.ToolCall toolCall = iterator.next(); // 获取当前元素
                FunctionCallback functionCallback = functionCallbackRegister.get(toolCall.function().name());
                String call = functionCallback.call(toolCall.function().arguments());
                log.info(call);
                // 如果不是最后一个元素，继续迭代
                if (iterator.hasNext()) {
                } else {
//                     如果是最后一个元素，执行额外的逻辑

                    chatCompletionChunkResponseEntity1 = ChatRequestExample.requestDeepSeekChat(null, List.of(
                            system,
                            user,
                            new ChatRequest.Message("user", call)
                    ));

                }
            }
        }

        return ResponseEntity.ok(chatCompletionChunkResponseEntity1.getBody().choices().get(0).message().content());

    }

    @PostMapping("/test/select")
    @IgnoreAuth
    public Result<List<String>> testSelect(@RequestBody Note category){
        List<Map<String, Object>> maps = noteService.testSelect(category.getContent());
// 1. 使用 Set 集合来自动存储唯一的关键词
        Set<String> allKeywordsSet = new HashSet<>();

// 2. 遍历从数据库返回的每一行结果（每个 Map 对象）
        for (Map<String, Object> rowMap : maps) {
            // 根据键名 "note_key_word" 获取其值
            Object rawValue = rowMap.get("note_key_word");

            // 确保值是一个有效的字符串
            if (rawValue instanceof String) {
                String keywordStr = (String) rawValue;

                // 检查字符串是否有效，且不是空的方括号 "[]"
                if (!keywordStr.trim().isEmpty() && keywordStr.length() > 2) {

                    // a. 去掉首尾的方括号，例如："[关键词1, 关键词2]" -> "关键词1, 关键词2"
                    String cleanedStr = keywordStr.substring(1, keywordStr.length() - 1);

                    // b. 根据 ", "（逗号加空格）分割字符串，得到独立的关键词数组
                    String[] keywords = cleanedStr.split(", ");

                    // c. 将这个数组中的所有关键词添加到我们的 Set 集合中
                    allKeywordsSet.addAll(Arrays.asList(keywords));
                }
            }
        }

// 3. 如果您最终需要的是 List 类型，可以将 Set 转换为 List
        List<String> finalKeywordList = new ArrayList<>(allKeywordsSet);
        log.debug("查看数据:{}",maps);
        return Result.OK(finalKeywordList);
    }

    //检索分类的关键词
    @PostMapping("/search/keywords")
    @IgnoreAuth
    public Result<List<String>> searchKeywords(@RequestBody Note category) {
        List<Map<String, Object>> maps = noteService.testSelect(category.getContent());
        Set<String> allKeywordsSet = new HashSet<>();

// 2. 遍历从数据库返回的每一行结果（每个 Map 对象）
        for (Map<String, Object> rowMap : maps) {
            // 根据键名 "note_key_word" 获取其值
            Object rawValue = rowMap.get("note_key_word");
            // 确保值是一个有效的字符串
            if (rawValue instanceof String) {
                String keywordStr = (String) rawValue;

                // 检查字符串是否有效，且不是空的方括号 "[]"
                if (!keywordStr.trim().isEmpty() && keywordStr.length() > 2) {
                    // a. 去掉首尾的方括号，例如："[关键词1, 关键词2]" -> "关键词1, 关键词2"
                    String cleanedStr = keywordStr.substring(1, keywordStr.length() - 1);
                    // b. 根据 ", "（逗号加空格）分割字符串，得到独立的关键词数组
                    String[] keywords = cleanedStr.split(", ");
                    // c. 将这个数组中的所有关键词添加到我们的 Set 集合中
                    allKeywordsSet.addAll(Arrays.asList(keywords));
                }
            }
        }
        List<String> finalKeywordList = new ArrayList<>(allKeywordsSet);
        log.debug("查看数据:{}", maps);
        return Result.OK(finalKeywordList);
    }
    //根据分类获取子分类
    @GetMapping("/search/children/{id}")
    @IgnoreAuth
    public Result<List<Map<String, Object>>> getChildrenCategories(@PathVariable Long id) {
        List<Map<String, Object>> childrenCategories = noteService.getChildrenCategories(id);
        return Result.OK(childrenCategories);
    }

    public static void main(String[] args) {

    }
}



